﻿using ChoMy.Areas.Admin.Models;
using ChoMy.Constants;
using ChoMy.Helpers;
using ChoMy.Models;
using ChoMy.Models.Data;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ChoMy.Controllers
{
    public class TrendController : Controller
    {
        private ChoMyDbContext db = new ChoMyDbContext();

        [Authorize(Roles = "Admin, Read Trend")]
        public ActionResult Index(string search, string sortOrder, int? page, int? pageSize)
        {
            var sortList = new List<string> { "Name", "DateModified", "DateCreated" };
            var pageSizeList = new List<int> { 10, 25, 50, 100 };
            int pageNumber = page ?? 1;

            pageSize = pageSize ?? 10;
            sortOrder = sortOrder ?? "DateCreated_desc";

            ViewBag.PageSize = pageSize;
            ViewBag.PageSizeDDL = new SelectList(pageSizeList, pageSize);

            IQueryable<Trend> query = db.Trends.Where(x => !x.IsDelete);

            if (!String.IsNullOrWhiteSpace(search))
            {
                page = 1;

                query = Search(query, search.Trim());
            }

            query = Sort(query, sortOrder, sortList);

            return View(query.ToPagedList(pageNumber, (int)pageSize));
        }

        [Authorize(Roles = "Admin, Manage Trend")]
        public ActionResult Manage(int? id, string search, string sortOrder, int? page, int? pageSize)
        {
            if (id == null)
            {
                return RedirectToAction("BadRequest", "Error");
            }

            Trend trend = db.Trends.Find(id);

            if (trend == null)
            {
                return RedirectToAction("NotFound", "Error");
            }

            ViewBag.Trend = trend;

            List<int> ids = trend.TrendProducts.Select(x => x.ProductId).ToList();

            var sortList = new List<string> { "Name", "ListPrice" };
            var pageSizeList = new List<int> { 10, 25, 50, 100 };
            int pageNumber = page ?? 1;

            pageSize = pageSize ?? 10;
            sortOrder = sortOrder ?? "DateCreated_desc";

            ViewBag.PageSize = pageSize;
            ViewBag.PageSizeDDL = new SelectList(pageSizeList, pageSize);

            IQueryable<Product> query = db.Products.Where(x => !x.IsDelete && !ids.Contains(x.Id));

            if (!String.IsNullOrWhiteSpace(search))
            {
                page = 1;

                query = Search(query, search.Trim());
            }

            query = Sort(query, sortOrder, sortList);

            return View(query.ToPagedList(pageNumber, (int)pageSize));
        }

        [HttpPost]
        public ActionResult Manage(List<int> productIds, int trendId, string command, string returnListUrl)
        {
            if (productIds.Count > 0)
            {
                if (command == "Add")
                {
                    foreach (int id in productIds)
                    {
                        var model = new TrendProduct();
                        model.TrendId = trendId;
                        model.ProductId = id;

                        db.TrendProducts.Add(model);
                    }

                    db.SaveChanges();
                }
                else
                {
                    foreach (int id in productIds)
                    {
                        TrendProduct model = db.TrendProducts
                            .FirstOrDefault(x => x.ProductId == id && x.TrendId == trendId);

                        if (model != null)
                        {
                            db.TrendProducts.Remove(model);
                        }
                    }

                    db.SaveChanges();
                }
            }

            return Redirect(returnListUrl);
        }

        [Authorize(Roles = "Admin, Read Trend")]
        public ActionResult Details(int? id, string returnListUrl)
        {
            if (id == null)
            {
                return RedirectToAction("BadRequest", "Error");
            }

            Trend om = db.Trends.Find(id);

            if (om == null)
            {
                return RedirectToAction("NotFound", "Error");
            }

            ViewBag.ReturnListUrl = returnListUrl;

            return View(om);
        }

        [Authorize(Roles = "Admin, Create Trend")]
        public ActionResult Create(string returnListUrl)
        {
            ViewBag.ReturnListUrl = returnListUrl;

            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(CreateTrendViewModel model, string returnListUrl)
        {
            if (ModelState.IsValid)
            {
                var om = new Trend();
                om.Name = model.Name.Trim();
                om.NameId = StringHelper.Unsigned(om.Name);

                if (FileHelper.IsValid(model.TypeImage))
                {
                    om.TypeImageUrl = FileHelper.Upload(model.TypeImage, om.Name, "/Upload/Image/Trend/Type/");
                }

                if (FileHelper.IsValid(model.ContentImage))
                {
                    om.ContentImageUrl = FileHelper.Upload(model.ContentImage, om.Name, "/Upload/Image/Trend/Content/");
                }

                db.Trends.Add(om);
                db.SaveChanges();

                SaveHistory("create-success", om.Name);
                AlertHandling("create-success", om.Name);

                if (!String.IsNullOrWhiteSpace(returnListUrl))
                {
                    return Redirect(returnListUrl);
                }

                return RedirectToAction("Index");
            }

            ViewBag.ReturnListUrl = returnListUrl;

            return View(model);
        }

        [Authorize(Roles = "Admin, Edit Trend")]
        public ActionResult Edit(int? id, string returnListUrl)
        {
            if (id == null)
            {
                return RedirectToAction("BadRequest", "Error");
            }

            Trend om = db.Trends.Find(id);

            if (om == null)
            {
                return RedirectToAction("NotFound", "Error");
            }

            var model = new EditTrendViewModel();
            model.Id = om.Id;
            model.Name = om.Name;

            ViewBag.ReturnListUrl = returnListUrl;

            return View(model);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(EditTrendViewModel model, string returnListUrl)
        {
            if (ModelState.IsValid)
            {
                Trend om = db.Trends.Find(model.Id);
                om.Name = model.Name.Trim();
                om.NameId = StringHelper.Unsigned(om.Name);
                om.DateModified = DateTime.Now;
                om.ModifiedBy = User.Identity.Name;

                if (FileHelper.IsValid(model.TypeImage))
                {
                    FileHelper.Delete(om.TypeImageUrl);
                    om.TypeImageUrl = FileHelper.Upload(model.TypeImage, om.Name, "/Upload/Image/Trend/Type/");
                }

                if (FileHelper.IsValid(model.ContentImage))
                {
                    FileHelper.Delete(om.ContentImageUrl);
                    om.ContentImageUrl = FileHelper.Upload(model.ContentImage, om.Name, "/Upload/Image/Trend/Content/");
                }

                db.Entry(om).State = EntityState.Modified;
                db.SaveChanges();

                SaveHistory("edit-success", om.Name);
                AlertHandling("edit-success", om.Name);

                if (!String.IsNullOrWhiteSpace(returnListUrl))
                {
                    return Redirect(returnListUrl);
                }

                return RedirectToAction("Index");
            }

            ViewBag.ReturnListUrl = returnListUrl;

            return View(model);
        }

        [Authorize(Roles = "Admin, Delete Trend")]
        public ActionResult Delete(int? id, string returnListUrl)
        {
            if (id == null)
            {
                return RedirectToAction("BadRequest", "Error");
            }

            Trend om = db.Trends.Find(id);

            if (om == null)
            {
                return RedirectToAction("NotFound", "Error");
            }

            ViewBag.ReturnListUrl = returnListUrl;

            return View(om);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id, string returnListUrl)
        {
            Trend om = db.Trends.Find(id);
            om.IsDelete = true;
            om.DateModified = DateTime.Now;
            om.ModifiedBy = User.Identity.Name;

            db.Entry(om).State = EntityState.Modified;
            db.SaveChanges();

            SaveHistory("delete-success", om.Name);
            AlertHandling("delete-success", om.Name);

            if (!String.IsNullOrWhiteSpace(returnListUrl))
            {
                return Redirect(returnListUrl);
            }

            return RedirectToAction("Index");
        }

        [HttpPost]
        public ActionResult CheckName(string name, int? id)
        {
            string tmp = StringHelper.Unsigned(name);

            Trend om = db.Trends.FirstOrDefault(x => !x.IsDelete && x.NameId == tmp && x.Id != id);

            if (om != null)
            {
                string url = Url.Action("Details", new { id = om.Id });
                string result = String.Format("Tên xu hướng này đã tồn tại. <a href='{0}' target='_blank'>Chi tiết</a>", url);

                return Json(result, JsonRequestBehavior.AllowGet);
            }

            return Json(true, JsonRequestBehavior.AllowGet);
        }

        #region Helpers
        private void SaveHistory(string crud, string name)
        {
            string userName = User.Identity.Name;
            string description = "";

            switch (crud)
            {
                case "create-success":
                    description = String.Format("<b>{0}</b> tạo mới xu hướng <b>{1}</b>", userName, name);
                    break;
                case "edit-success":
                    description = String.Format("<b>{0}</b> chỉnh sửa xu hướng <b>{1}</b>", userName, name);
                    break;
                case "delete-success":
                    description = String.Format("<b>{0}</b> xóa xu hướng <b>{1}</b>", userName, name);
                    break;

            }

            var history = new History();
            history.DateTime = DateTime.Now;
            history.Description = description;
            history.HistoryTypeId = db.HistoryTypes.First(x => x.Name == "Trend").Id;

            db.Histories.Add(history);
            db.SaveChanges();
        }

        private void AlertHandling(string crud, string name)
        {
            string userName = User.Identity.Name;
            string alertMessage = "";
            string alertType = "alert-success";

            switch (crud)
            {
                case "create-success":
                    alertMessage = String.Format("Bạn vừa tạo mới xu hướng: <b>{0}</b>", name);
                    break;
                case "edit-success":
                    alertMessage = String.Format("Bạn vừa chỉnh sửa xu hướng: <b>{0}</b>", name);
                    break;
                case "delete-success":
                    alertMessage = String.Format("Bạn vừa xóa xu hướng: <b>{0}</b>", name);
                    break;
            }

            if (!String.IsNullOrWhiteSpace(alertMessage))
            {
                Session["alert-message-" + userName] = alertMessage;
                Session["alert-type-" + userName] = alertType;
            }
        }

        private IQueryable<Product> Search(IQueryable<Product> query, string search)
        {
            ViewBag.Search = search;

            search = StringHelper.Unsigned(search);

            query = query.Where(x => x.NameId.Contains(search));

            return query;
        }

        private IQueryable<Trend> Search(IQueryable<Trend> query, string search)
        {
            ViewBag.Search = search;

            search = StringHelper.Unsigned(search);

            query = query.Where(x => x.NameId.Contains(search));

            return query;
        }

        private IQueryable<Product> Sort(IQueryable<Product> query, string sortOrder, List<string> sortList)
        {
            ViewBag.SortOrder = sortOrder;

            foreach (string sort in sortList)
            {
                ViewData[sort + "Sort"] = sortOrder == sort + "_desc" ? sort : sort + "_desc";
            }

            if (sortOrder.Contains("_desc"))
            {
                sortOrder = sortOrder.Replace("_desc", "");
                query = query.OrderBy(sortOrder + " descending");
                ViewData[sortOrder + "Icon"] = DataTableConstant.DescSortIcon;
            }
            else
            {
                query = query.OrderBy(sortOrder);
                ViewData[sortOrder + "Icon"] = DataTableConstant.AscSortIcon;
            }

            return query;
        }

        private IQueryable<Trend> Sort(IQueryable<Trend> query, string sortOrder, List<string> sortList)
        {
            ViewBag.SortOrder = sortOrder;

            foreach (string sort in sortList)
            {
                ViewData[sort + "Sort"] = sortOrder == sort + "_desc" ? sort : sort + "_desc";
            }

            if (sortOrder.Contains("_desc"))
            {
                sortOrder = sortOrder.Replace("_desc", "");
                query = query.OrderBy(sortOrder + " descending");
                ViewData[sortOrder + "Icon"] = DataTableConstant.DescSortIcon;
            }
            else
            {
                query = query.OrderBy(sortOrder);
                ViewData[sortOrder + "Icon"] = DataTableConstant.AscSortIcon;
            }

            return query;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
        #endregion
    }
}